package com.yeyks.service.impl;

import com.yeyks.account.dal.domain.AccountInfo;
import com.yeyks.account.service.SysAppMenuService;
import com.yeyks.common.appcommon.dto.AppRouteDTO;
import com.yeyks.common.appcommon.dto.account.AppAccountDTO;
import com.yeyks.common.appcommon.dto.account.AppLoginAccountDTO;
import com.yeyks.common.appcommon.param.AppLoginOutParam;
import com.yeyks.common.appcommon.param.AppLoginParam;
import com.yeyks.common.appcommon.result.CommonResult;
import com.yeyks.common.utils.apputil.bean.MyBeanUtils;
import com.yeyks.common.utils.apputil.redis.RedisService;
import com.yeyks.common.utils.apputil.rediskey.BuilderKey;
import com.yeyks.commonReference.service.account.AccountInfoService;
import com.yeyks.entity.AppAccountInfo;
import com.yeyks.other.service.AddressDivisionService;
import com.yeyks.service.AppAccountTokenService;
import com.yeyks.service.AppLoginService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.yeyks.common.utils.apputil.rediskey.RedisKey.ACCOUNT_TOKEN;

/**
 * @author Administrator
 */
@Service("loginService")
@Slf4j
public class AppLoginServiceImpl implements AppLoginService {

    private RedisService redisService;

    private AddressDivisionService addressService;

    private AppAccountTokenService appAccountTokenService;

    private AccountInfoService accountInfoService;

    private SysAppMenuService appMenuService;


    @Autowired
    public AppLoginServiceImpl(
            RedisService redisService,
            AddressDivisionService addressService,
            AppAccountTokenService appAccountTokenService,
            AccountInfoService accountInfoService,
            SysAppMenuService appMenuService) {
        this.redisService = redisService;
        this.addressService = addressService;
        this.appAccountTokenService = appAccountTokenService;
        this.accountInfoService = accountInfoService;
        this.appMenuService = appMenuService;
    }

    @Override
    public CommonResult<AppLoginAccountDTO> loginIn(AppLoginParam appLoginParam) {

        AccountInfo accountInfo = accountInfoService.loginAccount(appLoginParam.getUsername(), appLoginParam.getPassword());
        if (accountInfo != null) {
            //如果账户被禁用, 直接返回信息
            if (!accountInfo.getValid()) {
                return CommonResult.failed("该账户已被禁用, 其联系上级管理员");
            }
            /*DTO转换*/
            AppLoginAccountDTO appLoginAccountDTO = new AppLoginAccountDTO();
            appLoginAccountDTO.setAppAccountDTO(MyBeanUtils.convert(accountInfo, AppAccountDTO.class));

            //将token存入redis中 key --> userId   value -- > token, 有效期10天
            String key = BuilderKey.build(ACCOUNT_TOKEN, accountInfo.getId());
            //判断redis的token是否存在,如果存在,不生成,如果没有则生成新的token
            String token;
            if (null != redisService.get(key) && !"".equals(redisService.get(key))) {
                token = redisService.get(key);
                //验证token的有效性,如果无效， 删除redis
                boolean flag = appAccountTokenService.isAvailable(token);
                if (!flag) {
                    redisService.remove(BuilderKey.build(ACCOUNT_TOKEN, accountInfo.getId()));
                    token = appAccountTokenService.userIdToken(accountInfo.getId());
                }
            } else {
                token = appAccountTokenService.userIdToken(accountInfo.getId());
            }

            appLoginAccountDTO.setToken(token);
            convertRouteDTO(appLoginAccountDTO);
            redisService.setAndExpire(key, token, 10L, TimeUnit.DAYS);
            return CommonResult.success(appLoginAccountDTO);
        }
        return CommonResult.failed("用户名或者密码错误");
    }

    @Override
    public CommonResult logout(AppLoginOutParam param) {

        CommonResult<AppAccountInfo> commonResult = appAccountTokenService.getAvailAccount(param.getToken(), param.getVersion(), param.getPlatform());
        if (null == commonResult.getData()) {
            return commonResult;
        }
        //清空缓存
        AppAccountInfo appAccountInfo = commonResult.getData();
        //String key = BuilderKey.build(ACCOUNT_TOKEN, appAccountInfo.getId());
        //redisService.remove(key);
        return CommonResult.success(null, "操作成功,请重新登录");
    }

    /**
     * 账户路由的控制
     * 1.需要根据不同的账户类型进行分类，需要优化
     *
     * @param loginAccountDTO 账号相关信息
     */
    private void convertRouteDTO(AppLoginAccountDTO loginAccountDTO) {

        AppAccountDTO accountDTO = loginAccountDTO.getAppAccountDTO();
        if (null != accountDTO) {
            List<AppRouteDTO> routeDTOList = appMenuService.selectByAccountId(Long.valueOf(accountDTO.getId()));
            if (!CollectionUtils.isEmpty(routeDTOList)) {
                accountDTO.setRouteList(routeDTOList);
            }
            accountDTO.setDivCode(getDivCode(accountDTO.getArea()));
        }
        loginAccountDTO.setAppAccountDTO(accountDTO);
    }


    /**
     * 根据地址名称得到 code
     *
     * @param address 地址area， 账号的地址
     * @return 返回结果
     */
    private String getDivCode(String address) {

        CommonResult<String> commonResult = addressService.getAddressCodeByDetailAddress(address);
        if (commonResult.getData() != null) {
            return commonResult.getData();
        }
        return null;
    }
}
